feat(project): add LLM-as-a-judge and code-based evaluator TUI wizards - #2468
Conversation
`agentcore add` now lists `evaluator` with a submenu for its two leaves, and a bare `add evaluator llm-as-a-judge` or `add evaluator code-based` on a TTY opens its wizard. - llm-as-a-judge asks for a name, level, model, instructions and a rating scale preset. The model step offers Bedrock and OpenResponses, each opening its own model ID input. Bedrock is prefilled with global.anthropic.claude-sonnet-4-6, because the Evaluator service sends a temperature and newer Claude models refuse it. - code-based asks for a name, level and Lambda: scaffold a new one (with a timeout step) or use an existing one by ARN. - Each handler and its wizard build their input through one shared builder, so they refuse the same input with the same message. - RouterScreen keeps command names in one column when a description wraps. - The evaluator leaf descriptions follow the other add commands, and promptPreview moves into the wizard module for both reviews to use.
|
Claude Security Review: no high-confidence findings. (run) |
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Looks good
Nice split of the existing CLI handlers into toAdd...EvaluatorInput builders shared with the TUI wizards — the tests that reuse run(...) and compare against the wizard's outcome give strong evidence the two paths stay in sync. A few things I checked and found fine:
RevealChoiceFieldre-validates onreturnwhen the user commits, so per-provider stored model IDs (BedrockvsOpenResponses) can't sneak an unvalidated value into the submit — only the currently-selected provider's value is used and it must be re-entered/validated to advance.evaluatorNameSchema+requireDeployedNameFitsruns live in the wizard and again intoAddCodeBasedEvaluatorInput/toAddLlmAsAJudgeEvaluatorInput, so the CLI path is still guarded.- The
promptPreviewmove fromharness/screen.tsxtocomponents/wizard/fields.tsx(with its test relocated towizard.test.tsx) is a clean refactor and the harness tests were updated to match. DEFAULT_CODE_BASED_TIMEOUT_SECONDSnow lives in the schema module and is used consistently by the template and the wizard default.- The
RouterScreentwo-Box layout fix has a dedicated regression test for wrapping on narrow terminals.
No blocking issues found. LGTM to merge.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## refactor #2468 +/- ##
============================================
+ Coverage 97.24% 97.26% +0.02%
============================================
Files 617 620 +3
Lines 43848 44241 +393
============================================
+ Hits 42639 43033 +394
+ Misses 1209 1208 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Claude Security Review: no high-confidence findings. (run) |
|
|
||
| const ratingScale = resolveRatingScale(flags["rating-scale"]); | ||
|
|
||
| const resolver = new SourceResolver({ stdin: config.io.stdin }); |
There was a problem hiding this comment.
Model validation happens after resolving --instructions. With --instructions -, an invalid --model waits for stdin instead of failing immediately. We should validate model/name before source I/O
There was a problem hiding this comment.
Fixed in 4656785. The handler checks the deployed name and the model before it resolves --instructions, as it did before this PR. The wizard applies the same checks live on its name and model steps. A new test passes --instructions - with stdin left open. It timed out before the fix and now fails right away with the flag error.
| ); | ||
| } | ||
|
|
||
| export function promptPreview(prompt: string): string { |
There was a problem hiding this comment.
We should add back the length cap to this
There was a problem hiding this comment.
Fixed in 4656785. The first line is capped at 60 characters again, followed by the line count. Tests cover a long single line and a long first line.
tejaskash
left a comment
There was a problem hiding this comment.
- P1 — Path traversal in managed evaluator scaffolding
src/handlers/project/add/evaluator/code-based/index.ts:22
The headless--nameaccepts any nonempty string, while the managed branch never appliesEvaluatorNameSchema. A name such as../outsidereaches filesystem path construction, can scaffold outside the project, and cleanup targets the wrong path. Validate the complete managed input before returning it. This vulnerability predates the PR but remains in the newly extracted validation boundary
- llm-as-a-judge checks the deployed name and the model before reading --instructions, so `--instructions -` no longer waits on stdin when a flag is already invalid. - The managed code-based branch validates its whole scaffold input against the evaluator schema before scaffolding. A --name such as ../outside, or a malformed --kms-key-arn, used to scaffold first and fail at the spec write, which could leave files outside the project. - promptPreview caps the first line at 60 characters again.
|
Re the path traversal finding: confirmed and fixed in 4656785. I reproduced it with the real CLI. The managed branch now parses its whole scaffold input (name, level, description, KMS key, tags, timeout) against the evaluator schema before returning it. A bad name or KMS key now fails with exit code 2 and nothing on disk. A new test covers both and fails on the old code. The wizard was not affected, because its name step already applies |
|
Claude Security Review: no high-confidence findings. (run) |
notgitika
left a comment
There was a problem hiding this comment.
LGTM but there is a merge conflict
…evaluator-tui # Conflicts: # src/components/RouterScreen.tsx
e0454ca
|
Claude Security Review: no high-confidence findings. (run) |
Description
What. A bare
agentcore add evaluator llm-as-a-judgeoragentcore add evaluator code-basedon a TTY opens a wizard.add evaluatorjoins the add menu as a submenu.RouterScreennow keeps command names in one column when a description wraps.Why. These were the evaluator entries in the add wizard design. The wizards ask only what has no default. Description, KMS key, tags and inline rating scales stay flag-only. Instruction placeholders are not checked locally, following #2124, which leaves that check to the service.
The Bedrock judge defaults to
global.anthropic.claude-sonnet-4-6. The Evaluator service sendstemperature: 0.0, and Claude Opus 4.7 and every later Claude model refuse it. I checked every active Anthropic profile in us-west-2.Related Issue
Closes #
Documentation PR
Not applicable.
command.mdis regenerated for the two shorter descriptions.Type of Change
Testing
bun test(3729 pass, 0 fail),typecheck,lint:check,format:check,buildACTIVE, then the stack was removed through the CLI